popover menu: Disappear on focus out
authorMatthias Clasen <mclasen@redhat.com>
Sun, 9 Jun 2019 14:08:18 +0000 (14:08 +0000)
committerMatthias Clasen <mclasen@redhat.com>
Sun, 9 Jun 2019 17:38:54 +0000 (17:38 +0000)
We try to keep focus inside by wrapping arrow keynav.
But focus can still escape. If it does, we want to
disappear, like any good menu should.

gtk/gtkpopovermenu.c

index 8bd6af266f47518ef45e37271d7e57185a09b5ae..3c570c1d450adcf2754093285b864e7693a17699 100644 (file)
@@ -26,6 +26,8 @@
 #include "gtkmenutracker.h"
 #include "gtkpopoverprivate.h"
 #include "gtkwidgetprivate.h"
+#include "gtkeventcontrollerkey.h"
+#include "gtkmain.h"
 
 
 /**
@@ -137,11 +139,26 @@ visible_submenu_changed (GObject        *object,
   g_object_notify (G_OBJECT (popover), "visible-submenu");
 }
 
+static void
+focus_out (GtkEventController *controller,
+           GdkCrossingMode     mode,
+           GdkNotifyType       detail,
+           GtkPopover         *popover)
+{
+  gboolean contains_focus;
+
+  g_object_get (controller, "contains-focus", &contains_focus, NULL);
+
+  if (!contains_focus)
+    gtk_popover_popdown (popover);
+}
+
 static void
 gtk_popover_menu_init (GtkPopoverMenu *popover)
 {
   GtkWidget *stack;
   GtkStyleContext *style_context;
+  GtkEventController *controller;
 
   stack = gtk_stack_new ();
   gtk_stack_set_vhomogeneous (GTK_STACK (stack), FALSE);
@@ -153,6 +170,10 @@ gtk_popover_menu_init (GtkPopoverMenu *popover)
 
   style_context = gtk_widget_get_style_context (GTK_WIDGET (popover));
   gtk_style_context_add_class (style_context, GTK_STYLE_CLASS_MENU);
+
+  controller = gtk_event_controller_key_new ();
+  g_signal_connect (controller, "focus-out", G_CALLBACK (focus_out), popover);
+  gtk_widget_add_controller (GTK_WIDGET (popover), controller);
 }
 
 static void